const promisify = api => {
  return (options, ...params) => {
    return new Promise((resolve, reject) => {
      api(
        Object.assign({}, options, {
          success: resolve,

          fail: e => {
            if (e && e.errMsg) {
              reject(new Error(e.errMsg));
            } else {
              reject(new Error(`${api} fail`));
            }
          },
        }),
        ...params,
      );

      Promise.prototype.finally = function(callback) {
        let P = this.constructor;

        return this.then(
          value => P.resolve(callback()).then(() => value),
          reason =>
            P.resolve(callback()).then(() => {
              throw reason;
            }),
        );
      };
    });
  };
};

function isPromiseApi(key) {
  return !(
    (/^on|^create|Sync$|Manager$|^pause/.test(key) &&
      key !== 'createBLEConnection') ||
    key === 'stopRecord' ||
    key === 'stopVoice' ||
    key === 'stopBackgroundAudio' ||
    key === 'stopPullDownRefresh' ||
    key === 'hideKeyboard' ||
    key === 'hideToast' ||
    key === 'hideLoading' ||
    key === 'showNavigationBarLoading' ||
    key === 'hideNavigationBarLoading' ||
    key === 'canIUse' ||
    key === 'navigateBack' ||
    key === 'closeSocket' ||
    key === 'closeSocket' ||
    key === 'pageScrollTo' ||
    key === 'drawCanvas' ||
    key === 'setHelp' ||
    key === 'setGlobalData'
  );
}

let pm = {};
if (uni) {
  uni.globalData = {};
  uni.Help = {};

  uni.setGlobalData = function(v) {
    uni.globalData = v;
  };
  uni.setHelp = function(v) {
    uni.Help = v;
  };
  pm = new Proxy(
    {},
    {
      get: function(target, propKey, receiver) {
        console.debug('get', target, propKey, receiver);
        if (isPromiseApi(propKey) && typeof uni[propKey] == 'function') {
          return function(argv) {
            const result = uni[propKey](argv);
            if (result && typeof result.then !== 'undefined') {
              return result.then(res => {
                if (res[0]) {
                  throw res[0];
                } else {
                  return res[1];
                }
              });
            } else {
              return result;
            }
          };
        } else {
          return Reflect.get(uni, propKey, receiver);
        }
      },
    },
  );
}

if (!uni) {
  const main = wx;

  for (let key in main) {
    if (main[key] !== undefined) {
      if (!isPromiseApi(key)) {
        pm[key] = main[key];
      } else {
        pm[key] = promisify(main[key]);
      }
    }
  }
}

export default pm;
